# -*- coding: utf-8 -*-

import sys,os
import random,time,inspect

from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext, Context, loader,Template
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from django.utils import translation
from django import forms
from django.core import serializers
from django.utils import simplejson

import django.core.urlresolvers

import settings


""" Serialize helpers """

def serializalot(query,extra={},field_methods={}):
    # Serialize a list of django objects (query) and some extra data to JSon.
    # The django objects are extended with data from calls to each method
    # listed in field_methods.
    result=dict(extra)     # start with the extra data
    result['results']=[]   # store the django object data in key results
    for django_obj in query:
        # start with the data that a normal django serialize would return
        obj={'pk':django_obj.pk, 'model':django_obj._meta.app_label+'.'+django_obj._meta.module_name, 'fields':{}}
        for field in django_obj._meta.fields:
            if str(field.get_internal_type())=='ForeignKey':
                obj['fields'][field.name]=getattr(django_obj,field.name)
                if obj['fields'][field.name]: obj['fields'][field.name]=obj['fields'][field.name].pk
            else:
                obj['fields'][field.name]=getattr(django_obj,field.name)
                if str(field.get_internal_type())=='DateTimeField':
                    obj['fields'][field.name]=str(obj['fields'][field.name])
        # add the field_methods data
        for field in field_methods:
            obj['fields'][field[0]]=getattr(django_obj,field[0])()
        result['results'].append(obj)
    # convert into JSon and return the result
    return simplejson.dumps(result)


""" Model helpers """

def get_field_listing(modelcls,include_fields=[]):
    # Returns a list with all fields in the modelcls, or just
    # the fields in the include_fields argument.
    fields=[]
    for f in modelcls._meta.fields:
        if f.name!='id':
            if f.name in include_fields or len(include_fields)==0:
                if str(f.get_internal_type())=='ForeignKey':
                    related=f.related.name
                else:
                    related=''
                ft=[f.name, 'fields.'+f.name, f.get_internal_type(), f.verbose_name, related, f.editable, f.blank]
                fields.append(ft)
    return fields

def get_related_lists(modelcls):
    # Return a dictionary with all data related to a given model
    # used for dropdowns.
    related={}
    for f in modelcls._meta.fields:
        if str(f.get_internal_type())=='ForeignKey':
            name=f.related.parent_model.__name__
            data=[]
            for o in f.related.parent_model.objects.all():
                data.append( (o.id,str(o)) )
            related[f.name]=data
    return related

def get_ext_setting(admin_cls,key,default=False):
    if key in admin_cls.__dict__:
        return admin_cls.__dict__[key]
    return default


""" Test View """

def test(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls
    return HttpResponse(serializalot(model_cls.objects.all(),{'recordsReturned':5}))


""" Main view """

def main_view(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls
    if admin_cls.view=='list':
        return list_view(request,admincls)
    if admin_cls.view=='tree':
        return tree_view(request,admincls)
    return HttpResponse('unknown admin_cls.view')


""" List view """

def list_view(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls

    c={}
    c['model']=model_cls.__name__
    c['template_inherits']=admin_cls.template_inherits
    c['page_size']=admin_cls.page_size
    c['caption']=get_ext_setting(model_cls, 'caption', 'Caption')
    c['description']=get_ext_setting(model_cls,'description','')

    pre_url=request.path_info.split('/')[1]
    c['pre_url']=pre_url
    c['json_list_url']='/'+pre_url+'/list/json/'
    c['json_save_url']='/'+pre_url+'/save/json/'
    c['json_delete_url']='/'+pre_url+'/delete/json/'

    list_fieldnames=admin_cls.fields_list
    edit_fieldnames=admin_cls.fields_edit

    c['rights']=get_ext_setting(model_cls, 'rights', {'edit':True, 'add':True, 'delete':True })

    c['list_fields']=[('pk','pk','AutoField','ID')]
    c['list_fields'].extend(get_field_listing(model_cls,list_fieldnames))
    c['fields_list_methods']=admin_cls.fields_list_methods

    c['edit_fields']=[('pk','pk','AutoField','ID')]
    c['edit_fields'].extend(get_field_listing(model_cls,edit_fieldnames))

    c['filter']=''
    c['filter_caption']=''
    c['filter_on']=False
    for k,v in request.GET.items():
        if 'filter.' in k:
            c['filter']='?'+k+'='+v
            k=k[7:]
            c['filter_caption']=' (filter on '+k+')'
            c['filter_on']=True

    related=get_related_lists(model_cls)
    c['related']={}
    for k in related.keys():
        c['related'][k]=related[k]

    c['object_actions']= get_ext_setting(admin_cls,'object_actions',[])

    r=render_to_response(admin_cls.template,RequestContext(request,c))
    return r

def list_json(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls

    e={}

    # Get all the objects from model and apply sort
    if 'sort' in request.POST:
        s=request.POST['sort']
        if request.POST.get('dir','ASC')!='ASC': s='-'+s
        q=model_cls.objects.all().order_by(s)
    else:
        q=model_cls.objects.all()

    for k,v in request.GET.items():
        if 'filter.' in k:
            k=str(k[7:])
            filter_by = { k+'__'+'id' : 3 }
            q=q.filter(**filter_by)

    #    filter_by = { '%s__%s' % (request.POST['name'], 'istartswith') : request.GET['query'] }
    #    q=modelcls.objects.all().filter(**filter_by)

    if 'pk' in request.GET:
        # If a specific pk i supplied, then only return
        # that object
        q=[q.get(pk=request.GET['pk'])]
        e['total']=1
    else:
        # Otherwise count the record in the query
        e['total']=q.count()

    # Handle pagination, if used
    if 'start' in request.POST and 'limit' in request.POST:
        p1=int(request.POST['start'])
        p2=int(request.POST['limit'])+p1
        q=q[p1:p2]

    # Resulting record count after pagination
    e['recordsReturned']=len(q)

    # Insert the recordlist into the final JSon reply
    e['results']='%results%' # serializers.serialize('json', q)

    #c=simplejson.dumps(e).replace('"%results%"',serializers.serialize('json', q))

    c=serializalot(q,e,admin_cls.fields_list_methods)

    return HttpResponse(c)

def save_json(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls

    pk=request.POST['pk']
    if pk=='':
        # Its a new object
        q=model_cls()
    else:
        # Its an existing object
        q=model_cls.objects.get(pk=pk)
    for f in model_cls._meta.fields:
        if f.name!='id':
            if f.name in request.POST:
                v=request.POST[f.name]
                print f.name,f.get_internal_type(),v
                if f.get_internal_type()!='ForeignKey':
                    if f.get_internal_type() in ['DateField','DateTimeField']:
                        if v=='':
                            v=None
                    if v:
                        try:
                            print ' ',f.name,'=',v
                            setattr(q,f.name,v)
                        except:
                            print 'Error, count not set field',f.name,'to value',v
                else:
                    # save foreignkey
                    #print dir(f)
                    #print f.related
                    #print f.name
                    if v<>'':
                        ro=f.related.parent_model.objects.get(pk=int(v))
                        setattr(q,f.name,ro)
    q.save()

    r={'success':True, 'msg':'Ok!'}
    return HttpResponse(simplejson.dumps(r))

def delete_json(request,model,id):
    model=getattr(sys.modules[__name__],model)
    o=model.objects.get(pk=id)
    o.delete()
    return HttpResponse("OK")


""" Tree view """

def tree_view(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls

    c={}

    c['model']=model_cls.__name__
    c['template_inherits']=admin_cls.template_inherits
    c['caption']=get_ext_setting(model_cls, 'caption', 'Caption')
    c['description']=get_ext_setting(model_cls,'description','')

    c['rights']=get_ext_setting(model_cls, 'rights', {'edit':True, 'add':True, 'delete':True })

    pre_url=request.path_info.split('/')[1]
    c['pre_url']=pre_url
    c['json_tree_url']='/'+pre_url+'/tree/json/'
    c['json_reparent_url']='/'+pre_url+'/tree/reparent/json/'
    c['json_reorder_url']='/'+pre_url+'/tree/reorder/json/'

    c['config']=simplejson.dumps(c)

    r=render_to_response(admin_cls.template,RequestContext(request,c))
    return r

def tree_json(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls

    root=request.POST['node']
    if root=='root':
        root=None

    query=model_cls.objects.filter(parent=root)
    result=[]
    for o in query:
        d={}
        f=getattr(o,admin_cls.field)
        if callable(f): f=f()
        d['text']=f
        d['id']=o.id
        if o.children.all().count()>0:
            d['cls']='folder'
        else:
            d['iconCls']='mycls'
            #d['leaf']=False
        result.append(d)

    return HttpResponse(simplejson.dumps(result))

def tree_reparent_json(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls
    node=request.POST['node']
    parent=request.POST['parent']
    if parent=='root':
        parent=None
    else:
        parent=model_cls.objects.get(pk=parent)
    position=request.POST['position']
    o=model_cls.objects.get(pk=node)
    o.parent=parent
    o.index=position
    o.save()
    return HttpResponse(1)

def tree_reorder_json(request,admincls):
    admin_cls = django.core.urlresolvers.get_callable(admincls)
    model_cls = admin_cls.cls
    return HttpResponse(1)
